package com.ash.tx.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import com.ash.tx.bean.Book;
import com.ash.tx.bean.User;
import com.ash.tx.dao.BookDao;
import com.ash.tx.dao.UserDao;
import com.ash.tx.service.UserService;

/**
 * 使用PlatformTransactionManager 编程式事务
 * 
 * @author Ashin
 *
 */
@Service("userServiceImpl2")
public class UserServiceImpl2 implements UserService {

    @Autowired
    private BookDao bookDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private PlatformTransactionManager txManager;

    @Override
    public void purchase(User user, Book book, Integer num) {
        // 定义事务隔离级别，传播行为，
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        // 事务状态类，通过PlatformTransactionManager的getTransaction方法根据事务定义获取；获取事务状态后，Spring根据传播行为来决定如何开启事务
        TransactionStatus status = txManager.getTransaction(def);

        try {
            Book bookBought = bookDao.queryBook(book.getId());

            bookBought.setStockNum(bookBought.getStockNum() - num);

            if (bookBought.getStockNum() <= 0) {
                throw new RuntimeException("book stock num is not enough");
            }

            // 减库存
            bookDao.updateBook(bookBought);

            // 减余额
            User userPurchase = userDao.queryUser(user.getId());

            userPurchase.setBalance(userPurchase.getBalance() - bookBought.getPrice() * num);

            if (userPurchase.getBalance() <= 0) {
                throw new RuntimeException("balance is not enough");
            }

            userDao.updateUser(userPurchase);

            txManager.commit(status);

        } catch (RuntimeException e) {
            txManager.rollback(status);

            throw e;

        }
    }

}
